package com.brainshare.an.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.brainshare.an.domain.AnWechatUser;
import com.brainshare.an.mapper.AnWechatUserMapper;
import com.brainshare.an.service.IAnWechatUserMechanismService;
import com.brainshare.an.service.IAnWechatUserService;
import com.brainshare.common.constant.CacheConstants;
import com.brainshare.common.constant.NumberConstants;
import com.brainshare.common.constant.ServiceExceptionStatus;
import com.brainshare.common.core.domain.BaseEntity;
import com.brainshare.common.core.redis.RedisCache;
import com.brainshare.common.enums.EducationEnum;
import com.brainshare.common.enums.RedPacketType2Enum;
import com.brainshare.common.enums.SexEnum;
import com.brainshare.common.exception.ServiceException;
import com.brainshare.common.utils.*;
import com.brainshare.common.utils.ip.IpUtils;
import com.brainshare.system.domain.*;
import com.brainshare.system.domain.param.UserInfo1Param;
import com.brainshare.system.domain.param.UserInfo2Param;
import com.brainshare.system.domain.vo.AddRedPacketVO;
import com.brainshare.system.service.*;
import com.brainshare.utils.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户数据Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-04
 */
@Service
public class AnWechatUserServiceImpl implements IAnWechatUserService {
    @Autowired
    private AnWechatUserMapper anWechatUserMapper;
    @Autowired
    private IAnWechatUserMechanismService anWechatUserMechanismService;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    IRedPacketService redPacketService;

    @Autowired
    IRedPacketRecordService redPacketRecordService;

    @Autowired
    IRedPacketInfoService redPacketInfoService;

    @Autowired
    IAnRedPacketRecordService anRedPacketRecordService;

    @Autowired
    ISysBuriedPointService sysBuriedPointService;

    @Autowired
    ISysBuriedPointResultService sysBuriedPointResultService;


    public static String SHARE_LINK = "https://www.ainaoxingdong.com/brainshare/index.html";

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 查询用户数据
     *
     * @param wechatUserId 用户数据主键
     * @return 用户数据
     */
    @Override
    public AnWechatUser selectAnWechatUserByWechatUserId(Long wechatUserId) {
        return anWechatUserMapper.selectAnWechatUserByWechatUserId(wechatUserId);
    }

    @Override
    public AnWechatUser selectAnWechatUserByOpenId(String openId) {
        return anWechatUserMapper.selectAnWechatUserByOpenId(openId);
    }

    @Override
    public AnWechatUser selectAnWechatUserByPhoneNumber(String phoneNumber)
    {
        return anWechatUserMapper.selectAnWechatUserByPhoneNumber(phoneNumber);
    }


    /**
     * 查询用户数据列表
     *
     * @param anWechatUser 用户数据
     * @return 用户数据
     */
    @Override
    public List<AnWechatUser> selectAnWechatUserList(AnWechatUser anWechatUser) {
        List<AnWechatUser> anWechatUsers = anWechatUserMapper.selectAnWechatUserList(anWechatUser);
        //查询用户对应的推广信息
//        List<Long> wechatUserIds = anWechatUsers.stream().map(AnWechatUser::getWechatUserId).collect(Collectors.toList());
//        if (wechatUserIds.size() > 0) {
//            List<AnWechatUserMechanism> anWechatUserMechanisms = anWechatUserMechanismService.selectWechatUserMechanismByWechatUserIds(wechatUserIds);
//            anWechatUserMechanisms = anWechatUserMechanisms.stream().filter(item -> item.getIsDone() == 0L).collect(Collectors.toList());
//            for (AnWechatUser wechatUser : anWechatUsers) {
//                List<AnWechatUserMechanism> filterList = anWechatUserMechanisms.stream().filter(item -> item.getWechatUserId().equals(wechatUser.getWechatUserId())).collect(Collectors.toList());
//                if (filterList.size() > 0) {
//                    AnWechatUserMechanism anWechatUserMechanism = filterList.get(0);
//                    wechatUser.setScreeningScore(anWechatUserMechanism.getScreeningScore());
//                    wechatUser.setIsDone(anWechatUserMechanism.getIsDone());
//                    wechatUser.setIsMechanism(0L);
//                    wechatUser.setAuthTime(anWechatUserMechanism.getAuthTime());
//                    wechatUser.setScreeningSource(anWechatUserMechanism.getMechanismName());
//                } else {
//                    wechatUser.setIsDone(1L);
//                    wechatUser.setIsMechanism(1L);
//                }
//            }
//        }
        return anWechatUsers;
    }

    /**
     * 新增用户数据
     *
     * @param anWechatUser 用户数据
     * @return 结果
     */
    @Override
    public int insertAnWechatUser(AnWechatUser anWechatUser) {
        anWechatUser.setCreateTime(DateUtils.getNowDate());
        return anWechatUserMapper.insertAnWechatUser(anWechatUser);
    }

    /**
     * 修改用户数据
     *
     * @param anWechatUser 用户数据
     * @return 结果
     */
    @Override
    public int updateAnWechatUser(AnWechatUser anWechatUser) {
        anWechatUser.setUpdateTime(DateUtils.getNowDate());
        return anWechatUserMapper.updateAnWechatUser(anWechatUser);
    }

    @Override
    public boolean updateAnWechatUserInfo(AnWechatUser anWechatUser)
    {
        int result = updateAnWechatUser(anWechatUser);
        if (result > 0)
        {
            refreshCacheWechatUser(anWechatUser);
            return true;
        }
        return false;
    }

    @Override
    public AnWechatUser updateAnWechatUserInfoById(Long anWechatUserId)
    {
        AnWechatUser anWechatUser = this.selectAnWechatUserByWechatUserId(anWechatUserId);
        refreshCacheWechatUser(anWechatUser);
        return anWechatUser;
    }

    /**
     * 批量删除用户数据
     *
     * @param wechatUserIds 需要删除的用户数据主键
     * @return 结果
     */
    @Override
    public int deleteAnWechatUserByWechatUserIds(Long[] wechatUserIds) {
        return anWechatUserMapper.deleteAnWechatUserByWechatUserIds(wechatUserIds);
    }

    /**
     * 删除用户数据信息
     *
     * @param wechatUserId 用户数据主键
     * @return 结果
     */
    @Override
    public int deleteAnWechatUserByWechatUserId(Long wechatUserId) {
        return anWechatUserMapper.deleteAnWechatUserByWechatUserId(wechatUserId);
    }

    @Override
    public boolean SendSmsCode(String phone)
    {
        try
        {
            if (redisCache.hasKey(CacheConstants.SMS_CODE + phone))
            {
                throw new ServiceException("提示：不能重复发送", ServiceExceptionStatus.CODE_REPEAT);
            }
            StringBuilder randomCode = new StringBuilder();
            while (randomCode.length() < 4)
            {
                String randomNumber = String.valueOf(RandomUtil.randomInt(1, 9));
                randomCode.append(randomNumber);
            }
//            randomCode.setLength(0);
//            randomCode.append("1234");
//            redisCache.setCacheObject(CacheConstants.SMS_CODE + phone, randomCode, 60 * 3, TimeUnit.SECONDS);
//            return true;
            logger.info("手机号" + phone + "验证码" + randomCode);
            boolean result = SmsUtils.sendAliyunSms(phone, randomCode.toString());
            if (result)
            {
                logger.info("发送阿里云短信验证码成功！");
                redisCache.setCacheObject(CacheConstants.SMS_CODE + phone, randomCode, 60 * 3, TimeUnit.SECONDS);
                return true;
            }
        } catch (Exception e)
        {
            logger.error(e.getMessage());
            return false;
        }
        return false;
    }

    @Override
    public String anWechatUserLogin(String phone, String smsCode, String mechanismId, String shareId)
    {
        String redisSmsCode = redisCache.getCacheObject(CacheConstants.SMS_CODE + phone);
        if (StringUtils.isEmpty(redisSmsCode) || !redisSmsCode.equals(smsCode))
        {
            throw new ServiceException("验证码不正确或已失效", ServiceExceptionStatus.CODE_ERROR);
        }
        AnWechatUser anWechatUser = anWechatUserMapper.selectAnWechatUserByPhoneNumber(phone);
        if (anWechatUser == null)
        {
            Long ts = DateUtils.getTimeMillis();
            anWechatUser = new AnWechatUser();
            anWechatUser.setPhone(phone);
            anWechatUser.setCreateTime(new Date());
            if (!StringUtils.isNullOrEmpty(mechanismId))
            {
                anWechatUser.setMechanismId(Convert.toLong(AesUtils.decryptHex(mechanismId)));
            }
            if (!StringUtils.isNullOrEmpty(shareId))
            {
                redPacketService.addRedPacket(Convert.toLong(AesUtils.decryptHex(shareId)),anWechatUser.getPhone(),RedPacketType2Enum.SHARE.getCode());
            }
            int insertResult = anWechatUserMapper.insertAnWechatUser(anWechatUser);
            logger.info("ts:{}，新增用户结果：{}", ts, insertResult);
            if (insertResult > 0)
            {
                AddRedPacketVO addRedPacketVO = redPacketService.addRedPacket(anWechatUser.getWechatUserId(),anWechatUser.getPhone(), RedPacketType2Enum.ANALYSE.getCode());
                logger.info("ts:{}，发红包结果：{}", ts, addRedPacketVO);
                if (null != addRedPacketVO)
                {
                    Integer receiveResult = redPacketService.receiveRedPacket(anWechatUser.getWechatUserId(),anWechatUser.getPhone(), Integer.valueOf(addRedPacketVO.getRedPacketId()));
                    logger.info("ts:{}，收红包结果：{}", ts, receiveResult);
                }
            }
        }
        return refreshCustomerToken(anWechatUser);
    }

    @Override
    public int addUserInfo1(HttpServletRequest request, UserInfo1Param userInfo1Param) {
        long ts = DateUtils.getTimeMillis();
        logger.info("ts:{},填写第1部分基础信息，入参:{}", ts, userInfo1Param);
        checkUserInfo1Param(userInfo1Param);
        int updateResult = updateAnWechatUser(request,userInfo1Param);
        logger.info("ts:{},填写第1部分基础信息，结果:{}", ts, updateResult);
        return updateResult;
    }

    private int updateAnWechatUser(HttpServletRequest request, BaseEntity userInfoParam) {
        AnWechatUser anWechatUser = CommonUtils.getAnWechatUser(request);
        Long userId = anWechatUser.getWechatUserId();
        AnWechatUser user = new AnWechatUser();
        BeanUtils.copyProperties(userInfoParam, user);
        user.setWechatUserId(userId);
        user.setUpdateBy(String.valueOf(userId));
        user.setUpdateTime(DateUtils.getNowDate());
        int updateResult = anWechatUserMapper.updateAnWechatUser(user);
        if (updateResult > 0) {
            AnWechatUser wechatUser = anWechatUserMapper.selectAnWechatUserByWechatUserId(userId);
            refreshCacheWechatUser(wechatUser);
        }
        return updateResult;
    }

    void checkUserInfo1Param(UserInfo1Param userInfo1Param)
    {
        Assert.notNull(userInfo1Param.getNickName(),"昵称不能为空");
        Assert.state(RegexUtil.isValidNickName(userInfo1Param.getNickName()),"昵称只能输入10字符内中英文");
        Assert.notNull(userInfo1Param.getUserCardId(),"身份证号不能为空");
        Assert.state(RegexUtil.isValidIdCard(userInfo1Param.getUserCardId()),"身份证号不符合规则");
        Assert.notNull(userInfo1Param.getSex(),"性别不能为空");
        Assert.state(SexEnum.isValidateSexCode(String.valueOf(userInfo1Param.getSex())),"性别值不正确");
    }

    @Override
    public int addUserInfo2(HttpServletRequest request, UserInfo2Param userInfo2Param) {
        long ts = DateUtils.getTimeMillis();
        logger.info("ts:{},填写第2部分基础信息，入参:{}", ts, userInfo2Param);
        checkUserInfo2Param(userInfo2Param);
        int updateResult = updateAnWechatUser(request,userInfo2Param);
        logger.info("ts:{},填写第2部分基础信息，结果:{}", ts, updateResult);
        return updateResult;
    }

    void checkUserInfo2Param(UserInfo2Param userInfo2Param)
    {
        Assert.notNull(userInfo2Param.getAge(),"年龄不能为空");
        Assert.state(userInfo2Param.getAge()<Long.valueOf(NumberConstants.ONE_HUNDRED),"年龄只能小于100");
        Assert.notNull(userInfo2Param.getAddress(),"城市不能为空");
        Assert.notNull(userInfo2Param.getEducation(),"教育程度不能为空");
        Assert.state(EducationEnum.isValidateEducationCode(userInfo2Param.getEducation()),"教育程度值不正确");
    }

    @Override
    public int initUser(HttpServletRequest request,String phone) {
        long ts = DateUtils.getTimeMillis();
        try{
            String ip = IpUtils.getHostIp();
            logger.info("ts:{}，IP:{}，初始化用户{}开始========================================================================",ts,ip,phone);
            //用户
            AnWechatUser user = new AnWechatUser();
            user.setPhone(phone);
            List<AnWechatUser> anWechatUserList = anWechatUserMapper.selectAnWechatUserList(user);
            List<Long> idList = anWechatUserList.stream().map(item -> item.getWechatUserId()).collect(Collectors.toList());
            Long[] longIdList =  idList.toArray(new Long[idList.size()]);
            if (null==longIdList|| longIdList.length==0){
                logger.warn("ts:{}用户{}不存在",ts,phone);
                throw new Exception(String.format("用户%s不存在",phone));
            }
            int deleteUserResult = anWechatUserMapper.deleteAnWechatUserByWechatUserIds(longIdList);
            logger.info("ts:{}删除用户信息结果{}", ts, deleteUserResult);
            //红包记录
            Long userId = idList.get(0);
            RedPacketRecord redPacketRecord = new RedPacketRecord();
            redPacketRecord.setUserId(userId);
            List<RedPacketRecord> redPacketRecordList = redPacketRecordService.selectRedPacketRecordList(redPacketRecord);
            idList = redPacketRecordList.stream().map(item -> item.getId()).collect(Collectors.toList());
            longIdList =  idList.toArray(new Long[idList.size()]);
            if (null == longIdList || longIdList.length == 0) {
                logger.warn("ts:{}用户{}红包记录不存在", ts, phone);
                throw new Exception(String.format("用户%s红包记录不存在", phone));
            }
            int deleteRedPacketRecordResult = redPacketRecordService.deleteRedPacketRecordByIds(longIdList);
            logger.info("ts:{}删除红包记录结果{}", ts,deleteRedPacketRecordResult);
            //红包信息
            RedPacketInfo redPacketInfo = new RedPacketInfo();
            redPacketInfo.setUserId(userId);
            List<RedPacketInfo> redPacketInfoList = redPacketInfoService.selectRedPacketInfoList(redPacketInfo);
            idList = redPacketInfoList.stream().map(item -> item.getId()).collect(Collectors.toList());
            longIdList = idList.toArray(new Long[idList.size()]);
            if (null == longIdList || longIdList.length == 0) {
                logger.warn("ts:{}用户{}红包信息不存在", ts, phone);
                throw new Exception(String.format("用户%s红包信息不存在", phone));
            }
            int deleteRedPacketInfoResult = redPacketInfoService.deleteRedPacketInfoByIds(longIdList);
            logger.info("ts:{}删除红包信息结果{}", ts,deleteRedPacketInfoResult);

            //筛查领红包记录
            AnRedPacketRecord anRedPacketRecord = new AnRedPacketRecord();
            anRedPacketRecord.setUserId(userId);
            List<AnRedPacketRecord> anRedPacketRecordList = anRedPacketRecordService.selectAnRedPacketRecordList(anRedPacketRecord);
            idList = anRedPacketRecordList.stream().map(item -> item.getId()).collect(Collectors.toList());
            longIdList = idList.toArray(new Long[idList.size()]);
            if (null == longIdList || longIdList.length == 0) {
                logger.warn("ts:{}用户{}筛查领红包记录不存在", ts, phone);
                throw new Exception(String.format("用户%s筛查领红包记录不存在", phone));
            }
            int deleteAnRedPacketRecordResult = anRedPacketRecordService.deleteAnRedPacketRecordByIds(longIdList);
            logger.info("ts:{}删除筛查领红包记录结果{}",ts, deleteAnRedPacketRecordResult);

            //埋点记录
            SysBuriedPoint sysBuriedPoint = new SysBuriedPoint();
            sysBuriedPoint.setCustomerId(userId);
            List<SysBuriedPoint> sysBuriedPointList = sysBuriedPointService.selectSysBuriedPointList(sysBuriedPoint);
            idList = sysBuriedPointList.stream().map(item -> item.getId()).collect(Collectors.toList());
            longIdList =  idList.toArray(new Long[idList.size()]);
            if (null == longIdList || longIdList.length == 0) {
                logger.warn("ts:{}用户{}埋点记录不存在", ts, phone);
                throw new Exception(String.format("用户%s埋点记录不存在", phone));
            }
            int deleteBuriedPointResult = sysBuriedPointService.deleteSysBuriedPointByIds(longIdList);
            logger.info("ts:{}删除埋点明细结果{}",ts,deleteBuriedPointResult);
            //埋点结果表
            SysBuriedPointResult sysBuriedPointResult = new SysBuriedPointResult();
            sysBuriedPointResult.setUserId(userId);
            List<SysBuriedPointResult> sysBuriedPointResultList = sysBuriedPointResultService.selectSysBuriedPointResultList(sysBuriedPointResult);
            idList = sysBuriedPointResultList.stream().map(item -> item.getId()).collect(Collectors.toList());
            longIdList =  idList.toArray(new Long[idList.size()]);
            int deleteBuriedPointResultValue = 0;
            if (null != longIdList && longIdList.length > 0) {
                sysBuriedPointResultService.deleteSysBuriedPointResultByIds(longIdList);
                logger.info("ts:{}删除埋点结果值{}", ts, deleteBuriedPointResultValue);
            }
            logger.info("ts:{}，IP:{}，初始化用户{}结束========================================================================",ts,ip,phone);
            return deleteUserResult+deleteRedPacketRecordResult+deleteRedPacketInfoResult+deleteAnRedPacketRecordResult+deleteBuriedPointResult+deleteBuriedPointResultValue;
        }catch(Exception e){
            logger.error("ts:{}，初始化用户异常",ts,e);
            return NumberConstants.NEGATIVE_ONE;
        }

    }

    @Override
    public boolean anWechatUserLoginOut(HttpServletRequest request)
    {
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token))
        {
            throw new RuntimeException("token不能为空");
        }
        Collection<String> collection = redisCache.keys(CacheConstants.WECHAT_USER_TOKEN + "*" + ":" + token);
        if (collection.size() > 0)
        {
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
            }
            boolean result = redisCache.deleteObject(tokenKey);
            if (result)
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public String getAnWechatUserShareLink(AnWechatUser anWechatUser)
    {
        return SHARE_LINK + "?shareId=" + AesUtils.encryptHex(anWechatUser.getWechatUserId().toString());
    }

    /**
     * 刷新会员token信息
     * @param wechatUser
     * @return
     */
    public String refreshCustomerToken(AnWechatUser wechatUser)
    {
        Collection<String> collection = redisCache.keys(CacheConstants.WECHAT_USER_TOKEN + wechatUser.getPhone() + "*");
        if (collection.size() > 0)
        {
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
            }
            redisCache.deleteObject(tokenKey);
        }
        String token = UUID.randomUUID().toString();
        redisCache.setCacheObject(CacheConstants.WECHAT_USER_TOKEN + wechatUser.getPhone() + ":" + token, JSON.toJSONString(wechatUser), 3, TimeUnit.DAYS);
        return token;
    }

    /**
     * 刷新缓存中的会员信息
     * @param anWechatUser
     */
    public void refreshCacheWechatUser(AnWechatUser anWechatUser)
    {
        Collection<String> collection = redisCache.keys(CacheConstants.WECHAT_USER_TOKEN + anWechatUser.getPhone() + "*");
        if (collection.size() > 0)
        {
            Iterator iterator = collection.iterator();
            String tokenKey = "";
            while (iterator.hasNext())
            {
                tokenKey = iterator.next().toString();
            }
            redisCache.setCacheObject(tokenKey, JSON.toJSONString(anWechatUser));
        }
    }

}
